﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyGame
{
    public class CharacterClass
    {
        public CharacterStats Stats;
        public ArenaSquare Square
        {
            set
            {
                if (value != null)
                {
                    value.Character = this;
                }
                square = value;
            }
            get { return square; }
        }

        public GameEffect Boost;
        public GameEffect Drain;
        public SpecialAbility OffensiveAbility;
        public SpecialAbility DefensiveAbility;
        private ArenaSquare square;


        

        public CharacterClass(CharacterStats newStats, SpecialAbility offense, SpecialAbility defense)
        {
            Stats = newStats;
            OffensiveAbility = offense;
            offense.AbilityOwner = this;
            DefensiveAbility = defense;
            defense.AbilityOwner = this;

        }


        public virtual CharacterClass GetInstance(ArenaSquare position)
        {
            return new CharacterClass(
                    Stats.GetInstance(),
                    OffensiveAbility.GetInstance(OffensiveAbility.Power),
                    DefensiveAbility.GetInstance(DefensiveAbility.Power)
                    ) 
                    { 
                        Square = position,
                        Boost = new GameEffect(true),
                        Drain = new GameEffect(false)
                    
                    };

           
        }

        public void DealDefensiveDamage(CharacterClass damageTarget)
        {
            damageTarget.TakeDamage(
                Drain.ModifyDefenseDamage(
                    Boost.ModifyDefenseDamage(
                        Stats.Defense
                    )
                )
            );

        }

        public void DealOffensiveDamage(CharacterClass damageTarget)
        {

            damageTarget.TakeDamage(
                Drain.ModifyAttackDamage(
                    Boost.ModifyAttackDamage(
                        Stats.Attack
                    )
                )
            );
        }

        public void TakeDamage(int damage)
        {
           var totalDamage = 
                   Drain.ModifyDamageTaken(
                    Boost.ModifyDamageTaken(
                       damage
                    )
                );

           Stats.Health -= totalDamage;
        }

        public void TakeEffects(GameEffect boost, GameEffect drain )
        {
            var needNewBoost = boost != null && boost.Power >= Boost.Power;
            var needNewDrain = drain != null && drain.Power >= Drain.Power;
            var newBoost = needNewBoost ? 
                                    Drain.ModifyBoostTaken(Boost.ModifyBoostTaken(boost.GetInstance(boost.Power))) : 
                                    Boost;
            var newDrain = needNewDrain ? 
                                    Drain.ModifyBoostTaken(Boost.ModifyBoostTaken(drain.GetInstance(drain.Power))) :
                                    Drain;
            if(needNewBoost)
            {
                Boost.RevertStats(Stats);
                newBoost.ModifyStats(Stats);
            }
            if(needNewDrain)
            {
                Drain.RevertStats(Stats);
                newDrain.ModifyStats(Stats);
            }

            Boost = newBoost;
            Drain = newDrain;
        }

        public virtual void Rush(CharacterClass rushTarget, Arena arena,List<CharacterClass> additionalTargets)
        {
            InvolveEffectsInRush();
            rushTarget.InvolveEffectsInRush();
            //Attack can be replaced by ability
            if(!OffensiveAbility.ReplacesAttack )
                DealOffensiveDamage(rushTarget);
            rushTarget.DealDefensiveDamage(this);
            OffensiveAbility.Execute(rushTarget, arena, additionalTargets);
            if (rushTarget.Stats.Health > 0)
                rushTarget.DefensiveAbility.Execute(this, arena, null);

            DiscardUsedEffects();
            rushTarget.DiscardUsedEffects();
            
        }

        public virtual void InvolveEffectsInRush()
        {
            Drain.IsInvolvedInRush = true;
            Boost.IsInvolvedInRush = true;
        }

        public virtual void DiscardUsedEffects()
        {
            if (Drain.IsInvolvedInRush)
            {
                Drain.RevertStats(Stats);
                Drain = new GameEffect(false);
            }
            if (Boost.IsInvolvedInRush)
            {
                Boost.RevertStats(Stats);
                Boost = new GameEffect(true);
            }

        }
       
    }
}
